home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / rayshade / rayview / glmethods.c next >
C/C++ Source or Header  |  1994-08-01  |  21KB  |  1,037 lines

  1. /*
  2.  * glmethods.c
  3.  *
  4.  * Support routines for SGI/RS6000 machines.
  5.  *
  6.  * Copyright (C) 1989, 1991, Craig E. Kolb, Allan Snyder
  7.  *
  8.  * This software may be freely copied, modified, and redistributed
  9.  * provided that this copyright notice is preserved on all copies.
  10.  *
  11.  * You may not distribute this software, in whole or in part, as part of
  12.  * any commercial product without the express consent of the authors.
  13.  * 
  14.  * There is no warranty or other guarantee of fitness of this software
  15.  * for any purpose.  It is provided solely "as is".
  16.  *
  17.  * $Id: glmethods.c,v 4.0.1.4 92/01/10 17:17:39 cek Exp Locker: cek $
  18.  *
  19.  * $Log:    glmethods.c,v $
  20.  * Revision 4.0.1.4  92/01/10  17:17:39  cek
  21.  * patch3: Added heightfield support.
  22.  * 
  23.  * Revision 4.0.1.3  91/12/13  11:43:11  cek
  24.  * patch3: Spot direction and spread now set correctly.
  25.  * patch3: Set GLC_OLDPOLYGON to 0 on sgi machines to fix VGX weirdness.
  26.  * 
  27.  * Revision 4.0.1.2  91/10/10  22:45:27  cek
  28.  * patch1: Added spotlight support.
  29.  * 
  30.  * Revision 4.0.1.1  1991/09/29  15:28:36  cek
  31.  * patch1: Added support for transparency.
  32.  *
  33.  * Revision 4.0  91/07/17  17:38:43  kolb
  34.  * Initial version
  35.  * 
  36.  */
  37. #include <gl.h>
  38. #include <device.h>
  39. #include "rayshade.h" 
  40. #include "options.h"
  41. #include "viewing.h"
  42.  
  43. #include "libsurf/surface.h"
  44.  
  45. #include "libobj/box.h"
  46. #include "libobj/cone.h"
  47. #include "libobj/csg.h"
  48. #include "libobj/cylinder.h"
  49. #include "libobj/disc.h"
  50. #include "libobj/hf.h"
  51. #include "libobj/grid.h"
  52. #include "libobj/instance.h"
  53. #include "libobj/list.h"
  54. #include "libobj/plane.h"
  55. #include "libobj/poly.h"
  56. #include "libobj/sphere.h"
  57. #include "libobj/triangle.h"
  58.  
  59. #include "liblight/light.h"
  60. #include "liblight/extended.h"
  61. #include "liblight/infinite.h"
  62. #include "liblight/point.h"
  63. #include "liblight/spot.h"
  64.  
  65. #define CIRCLE_SAMPLES    20    /* # of samples around circle (cone/cyl/etc) */
  66. #define DEFAULT_NEAR    .2    /* default value for near clipping plane */
  67. #define DEFAULT_FAR    350.    /* default far clipping plane */
  68. #define PLANE_RAD    450.    /* radius of disc used to represent planes */
  69.  
  70. #ifndef SPHERELIB
  71. #define SPHERE_LEVEL    3
  72. #endif
  73.  
  74. /*
  75.  * Pass a normal stored in a Vector to the geometry pipeline.
  76.  */
  77. #define GLNormal(w)    (glnrm[0] = (w)->x, glnrm[1] = (w)->y, \
  78.              glnrm[2] = (w)->z, n3f(glnrm))
  79.  
  80. static void    GLBoxDraw(), GLConeDraw(), GLCsgDraw(), GLCylinderDraw(),
  81.         GLDiscDraw(),
  82.         GLGridDraw(), GLHfDraw(), GLInstanceDraw(),    
  83.         GLListDraw(), GLPlaneDraw(), GLPolygonDraw(),
  84.         GLSphereDraw(), GLTorusDraw(), GLTriangleDraw(),
  85.         GLBoundsDraw(),
  86.         GLInfiniteLight(), GLPointLight(), GLSpotLight(),
  87.         GLExtendedLight();
  88.  
  89. static short    cursurf = 1,
  90.         curlight = 1;
  91.  
  92. static Object    GLBoxObject,
  93.         GLCylObject,
  94.         GLSphereObject,
  95.         GLBoxObjectDefine(),
  96.         GLCylObjectDefine();
  97.  
  98. extern Object    GLSphereObjectDefine();
  99.  
  100. static int    Doublebuffered;
  101.  
  102. static float    Ident[4][4] =    {1., 0., 0., 0.,
  103.                  0., 1., 0., 0.,
  104.                  0., 0., 1., 0.,
  105.                  0., 0., 0., 1.},
  106.         glnrm[3];
  107.  
  108. static float **CirclePoints;
  109.  
  110. static void LightDraw(), GeomDraw(), GLMultMatrix(),
  111.         GLPushSurface(), GLPopSurface(), LightDrawInit(),
  112.         ObjectInit(), GLDrawFrame(), ScreenDrawInit(), DrawInit(),
  113.         GLUnitCircle(), GLDisc(), ComputeClippingPlanes();
  114.  
  115. Float CurrentTime;
  116.  
  117. static unsigned long BackPack;    /* Packed background color */
  118. static long Zinit;        /* maximum Zbuffer value */
  119.  
  120. MethodsRegister()
  121. {
  122.     BoxMethodRegister(GLBoxDraw);
  123.     ConeMethodRegister(GLConeDraw);
  124.     CsgMethodRegister(GLCsgDraw);
  125.     CylinderMethodRegister(GLCylinderDraw);
  126.     DiscMethodRegister(GLDiscDraw);
  127.     GridMethodRegister(GLGridDraw);
  128. #ifdef sgi
  129.     HfMethodRegister(GLHfDraw);
  130. #endif
  131.     InstanceMethodRegister(GLInstanceDraw);
  132.     ListMethodRegister(GLListDraw);
  133.     PlaneMethodRegister(GLPlaneDraw);
  134.     PolygonMethodRegister(GLPolygonDraw);
  135.     SphereMethodRegister(GLSphereDraw);
  136.     /*TorusMethodRegister(GLTorusDraw);*/
  137.     TriangleMethodRegister(GLTriangleDraw);
  138.  
  139.     InfiniteMethodRegister(GLInfiniteLight);
  140.     PointMethodRegister(GLPointLight);
  141.     ExtendedMethodRegister(GLExtendedLight);
  142.     SpotMethodRegister(GLSpotLight);
  143. }
  144.  
  145. void
  146. Render()
  147. {
  148.     short val;
  149.     float tmp;
  150.  
  151.     /*
  152.      * We're only sampling the scene once, so we need
  153.      * not do lots of work to determine exactly what
  154.      * animated transformations are doing...
  155.      */
  156.     Options.samples = 1;
  157.     SamplingSetOptions(Options.samples, Options.gaussian,
  158.                Options.filterwidth);
  159.  
  160.     DrawInit();
  161.     qdevice(ESCKEY);
  162.     qdevice(SPACEKEY);
  163.     qdevice(REDRAW);
  164.  
  165.     DrawFrames();
  166.  
  167.     while (TRUE) {
  168.         switch (qread(&val)) {
  169.             case ESCKEY:
  170.                 exit(0);
  171.                 break;
  172.             case REDRAW:
  173.                 reshapeviewport();
  174.                 DrawFrames();
  175.                 break;
  176.             case SPACEKEY:
  177.                 if (!val)
  178.                     DrawFrames();
  179.                 break;
  180.         }
  181.     }
  182. }
  183.  
  184. DrawFrames()
  185. {
  186.     int i;
  187.     for (i = 0; i < Options.totalframes; i++)
  188.         GLDrawFrame(i);
  189. }
  190.  
  191. static void
  192. DrawInit()
  193. {
  194.     extern Surface DefaultSurface;
  195.  
  196.     ScreenDrawInit();
  197.     ObjectInit();
  198.     LightDrawInit();
  199.  
  200.     /*
  201.      * Push the default surface.
  202.      */
  203.     GLPushSurface(&DefaultSurface);
  204. }
  205.  
  206. static void
  207. ScreenDrawInit()
  208. {
  209.     /*
  210.      * Open window, initialize graphics, etc.
  211.      */
  212. #ifdef sgi
  213.     foreground();
  214. #endif
  215.     prefsize(Screen.xsize, Screen.ysize);
  216.     winopen("rayview");
  217.  
  218. #ifdef sgi
  219.     glcompat(GLC_OLDPOLYGON, 0);
  220. #endif
  221.  
  222.     RGBmode();
  223.     mmode(MVIEWING);
  224.  
  225.     if (Options.totalframes > 1) {
  226.         Doublebuffered = TRUE;
  227.         doublebuffer();
  228.     }
  229.  
  230.  
  231.     gconfig();
  232.     blendfunction(BF_SA, BF_MSA);
  233.     zbuffer(TRUE);
  234.  
  235.     /*
  236.      * Initialize viewing matrix.
  237.      */
  238.     GLViewingInit();
  239.  
  240.     BackPack = (unsigned char)(255*Screen.background.r) |
  241.         ((unsigned char)(255*Screen.background.g) << 8) |
  242.         ((unsigned char)(255*Screen.background.b) << 16);
  243.     Zinit = getgdesc(GD_ZMAX);
  244.     lsetdepth(0, Zinit);
  245. }
  246.  
  247. /*
  248.  * Draw the World object.
  249.  */
  250. static void
  251. GLDrawFrame(frame)
  252. int frame;
  253. {
  254.     extern Geom *World;
  255.  
  256.     RSStartFrame(frame);
  257.     CurrentTime = Options.framestart;
  258.     TimeSet(CurrentTime);
  259.  
  260.     czclear(BackPack, Zinit);    
  261.  
  262.     /*
  263.      * Draw the World object
  264.      */
  265.     GeomDraw(World);
  266.     if (Doublebuffered)
  267.         swapbuffers();
  268. }
  269.  
  270. GLViewingInit()
  271. {
  272.     float near, far, aspect, dist, T[4][4];
  273.     short ang;
  274.     extern Geom *World;
  275.  
  276.     ang = Camera.vfov * 10 + 0.5;
  277.     aspect = Camera.hfov / Camera.vfov;
  278.  
  279.     T[0][0]=Screen.scrni.x; T[0][1]=Screen.scrnj.x; T[0][2]= -Camera.dir.x;
  280.     T[1][0]=Screen.scrni.y; T[1][1]=Screen.scrnj.y; T[1][2]= -Camera.dir.y;
  281.     T[2][0]=Screen.scrni.z; T[2][1]=Screen.scrnj.z; T[2][2]= -Camera.dir.z;
  282.  
  283.     T[0][3] = T[1][3] = T[2][3] = 0.;
  284.  
  285.     T[3][0] = -dotp(&Camera.lookp, &Screen.scrni);
  286.     T[3][1] = -dotp(&Camera.lookp, &Screen.scrnj);
  287.     T[3][2] = dotp(&Camera.lookp, &Camera.dir);
  288.     T[3][3] = 1.;
  289.  
  290.     ComputeClippingPlanes(&near, &far, World->bounds);
  291.  
  292.     loadmatrix(Ident);
  293.     perspective(ang, aspect, near, far);
  294.     polarview((float)Camera.lookdist, 0, 0, 0);
  295.     multmatrix(T);
  296. }
  297.  
  298.  
  299. static void
  300. ObjectInit()
  301. {
  302.     CircleDefine();
  303.     GLBoxObject = GLBoxObjectDefine();
  304.  
  305. #ifdef SPHERELIB
  306.     GLSphereObject = GLSphereObjectDefine();
  307. #else
  308.     GLSphereObject = GLSphereObjectDefine(SPHERE_LEVEL);
  309. #endif
  310.  
  311.     GLCylObject = GLCylObjectDefine();
  312. }
  313.  
  314. static void
  315. GeomDraw(obj)
  316. Geom *obj;
  317. {
  318.     Trans *ct;
  319.     /*
  320.      * If object has a surface associated with it,
  321.      * start using it.
  322.      */
  323.     if (obj->surf)
  324.         GLPushSurface(obj->surf);
  325.     if (obj->trans) {
  326.         /*
  327.          * Take care of any animated transformations that
  328.          * exist.
  329.          */
  330.         if (obj->animtrans && !equal(obj->timenow, CurrentTime)) {
  331.             TransResolveAssoc(obj->trans);
  332.             obj->timenow = CurrentTime;
  333.         }
  334.         pushmatrix();
  335.         /*
  336.           * Apply in reverse order.
  337.          */
  338.         for (ct = obj->transtail; ct; ct = ct->prev)
  339.             GLMultMatrix(&ct->trans);
  340.     }
  341.  
  342.     if (obj->methods->user) {
  343.         /*
  344.           * Call proper method
  345.           */
  346.         (*obj->methods->user)(obj->obj);
  347.     } else {
  348.         /*
  349.          * Draw bounding box.
  350.          */
  351.         GLBoundsDraw(obj->bounds);
  352.     }
  353.  
  354.     if (obj->surf)
  355.         GLPopSurface();
  356.     if (obj->trans)
  357.         popmatrix();
  358. }
  359.  
  360. static float surfprops[] =    {AMBIENT, 0, 0, 0,
  361.                  DIFFUSE, 0, 0, 0,
  362.                  SPECULAR, 0, 0, 0,
  363.                  SHININESS, 0,
  364.                  ALPHA, 1,
  365.                  LMNULL};
  366. static float    *amb = &surfprops[1],
  367.         *diff = &surfprops[5],
  368.         *spec = &surfprops[9],
  369.         *shine = &surfprops[13],
  370.         *alpha = &surfprops[15];
  371.  
  372. static void
  373. GLPushSurface(surf)
  374. Surface *surf;
  375. {
  376.     static Surface *lastsurf = NULL;
  377.  
  378.     /*
  379.      * Start using the given surface.
  380.      * In the case of the use of an "applysurf",
  381.      * the same surface will be applied to many
  382.      * primitives individually.  By saving the
  383.      * pointer to the last surface, we keep from
  384.      * lmdef'ing the surface when we don't need to.
  385.      */
  386.     if (surf != lastsurf) {
  387.         amb[0] = surf->amb.r; amb[1] = surf->amb.g;
  388.             amb[2] = surf->amb.b;
  389.         diff[0] = surf->diff.r; diff[1] = surf->diff.g;
  390.             diff[2] = surf->diff.b;
  391.         spec[0] = surf->spec.r; spec[1] = surf->spec.g;
  392.             spec[2] = surf->spec.b;
  393.         shine[0] = surf->srexp;
  394.         *alpha = 1. - surf->transp;
  395.         lmdef(DEFMATERIAL, cursurf, sizeof(surfprops)/sizeof(float),
  396.             surfprops);
  397.         lastsurf = surf;
  398.     }
  399.     lmbind(MATERIAL, cursurf);
  400.     cursurf++;
  401. }
  402.  
  403. static void
  404. GLMultMatrix(trans)
  405. RSMatrix *trans;
  406. {
  407.     float newmat[4][4];
  408.     /*
  409.      * Multiply in the given transformation.
  410.      */
  411.     newmat[0][0] = trans->matrix[0][0]; newmat[0][1] = trans->matrix[0][1];
  412.     newmat[0][2] = trans->matrix[0][2]; newmat[0][3] = 0.;
  413.     newmat[1][0] = trans->matrix[1][0]; newmat[1][1] = trans->matrix[1][1];
  414.     newmat[1][2] = trans->matrix[1][2]; newmat[1][3] = 0.;
  415.     newmat[2][0] = trans->matrix[2][0]; newmat[2][1] = trans->matrix[2][1];
  416.     newmat[2][2] = trans->matrix[2][2]; newmat[2][3] = 0.;
  417.     newmat[3][0] = trans->translate.x; newmat[3][1] = trans->translate.y;
  418.     newmat[3][2] = trans->translate.z ; newmat[3][3] = 1.;
  419.     multmatrix(newmat);
  420. }
  421.  
  422. static void
  423. GLPopSurface()
  424. {
  425.     cursurf--;
  426.     lmbind(MATERIAL, cursurf-1);
  427. }
  428.  
  429. static void
  430. GLBoundsDraw(bounds)
  431. Float bounds[2][3];
  432. {
  433.     float sx, sy, sz;
  434.  
  435.     pushmatrix();
  436.  
  437.     translate(bounds[LOW][X], bounds[LOW][Y], bounds[LOW][Z]);
  438.     scale(    bounds[HIGH][X] - bounds[LOW][X],
  439.         bounds[HIGH][Y] - bounds[LOW][Y],
  440.         bounds[HIGH][Z] - bounds[LOW][Z]);
  441.     pushmatrix();
  442.     callobj(GLBoxObject);
  443.     popmatrix();
  444.     popmatrix();
  445. }
  446.  
  447. static void
  448. GLBoxDraw(box)
  449. Box *box;
  450. {
  451.     GLBoundsDraw(box->bounds);
  452. }
  453.  
  454.  
  455. static void
  456. GLConeDraw(cone)
  457. Cone *cone;
  458. {
  459.     int i, j;
  460.     float norm[3], normconst, ZeroVect[3], tmpv[3];
  461.  
  462.     ZeroVect[0] = ZeroVect[1] = ZeroVect[2] = 0.;
  463.     /*
  464.      * Sides.
  465.      * For the normal, assume we are finding the normal at
  466.      * (C_P[i].x, C_P[i].y, 1.) at this point, the unnormalized
  467.      * normal = (C_P[i].x, C_P[i].y, -tantheta^2).  When we normalize,
  468.      * then length of the vector is simply equal to:
  469.      * sqrt(CP[i].x^2 + CP[i].y^2 + tantheta^4)  ==
  470.      * sqrt(1. + tantheta^4)
  471.      * In our case, tantheta = 1., so...
  472.      */
  473.  
  474.     normconst = 1. / sqrt(2.);
  475.     norm[2] = -normconst;
  476.  
  477.     pushmatrix();
  478.     GLMultMatrix(&cone->trans.trans);
  479.  
  480.     for (i = 0; i < CIRCLE_SAMPLES; i++) {
  481.         j = (i + 1) % CIRCLE_SAMPLES;
  482.         norm[0] = CirclePoints[i][0] * normconst;
  483.         norm[1] = CirclePoints[i][1] * normconst;
  484.         n3f(norm);
  485.         bgnpolygon();
  486.         if (cone->start_dist > EPSILON) {
  487.             tmpv[2] = cone->start_dist;
  488.             tmpv[0] = CirclePoints[i][0] * cone->start_dist;
  489.             tmpv[1] = CirclePoints[i][1] * cone->start_dist;
  490.             v3f(tmpv);
  491.             tmpv[0] = CirclePoints[j][0] * cone->start_dist;
  492.             tmpv[1] = CirclePoints[j][1] * cone->start_dist;
  493.             v3f(tmpv);
  494.         } else
  495.             v3f(ZeroVect);
  496.         tmpv[2] = 1.;
  497.         tmpv[0] = CirclePoints[j][0];
  498.         tmpv[1] = CirclePoints[j][1];
  499.         v3f(tmpv);
  500.         tmpv[0] = CirclePoints[i][0];
  501.         tmpv[1] = CirclePoints[i][1];
  502.         v3f(tmpv);
  503.         endpolygon();
  504.     }
  505.     popmatrix();
  506. }
  507.  
  508. static void
  509. GLCsgDraw(csg)
  510. Csg *csg;
  511. {
  512.     /*
  513.      * Punt by drawing both objects.
  514.      */
  515.     GeomDraw(csg->obj1);
  516.     GeomDraw(csg->obj2);
  517. }
  518.  
  519. static void
  520. GLCylinderDraw(cyl)
  521. Cylinder *cyl;
  522. {
  523.     pushmatrix();
  524.     GLMultMatrix(&cyl->trans.trans);
  525.     callobj(GLCylObject);
  526.     popmatrix();
  527. }
  528.  
  529. static void
  530. GLDiscDraw(disc)
  531. Disc *disc;
  532. {
  533.     GLDisc((Float)sqrt(disc->radius), &disc->pos, &disc->norm);
  534. }
  535.  
  536. static void
  537. GLDisc(rad, pos, norm)
  538. Float rad;
  539. Vector *pos, *norm;
  540. {
  541.     RSMatrix m, tmp;
  542.     Vector atmp;
  543.  
  544.     /*
  545.      * This is kinda disgusting...
  546.      */
  547.     ScaleMatrix(rad, rad, 1., &m);
  548.     if (fabs(norm->z) == 1.) {
  549.         atmp.x = 1.;
  550.         atmp.y = atmp.z = 0.;
  551.     } else {
  552.         atmp.x = norm->y;
  553.         atmp.y = -norm->x;
  554.         atmp.z= 0.;
  555.     }
  556.  
  557.     RotationMatrix(atmp.x, atmp.y, atmp.z, -acos(norm->z), &tmp);
  558.     MatrixMult(&m, &tmp, &m);
  559.     TranslationMatrix(pos->x, pos->y, pos->z, &tmp);
  560.     MatrixMult(&m, &tmp, &m);
  561.     pushmatrix();
  562.     GLMultMatrix(&m);
  563.     /*
  564.      * Draw unit circle.
  565.      */
  566.     GLUnitCircle(0., TRUE);
  567.     popmatrix();
  568. }
  569.  
  570. static void
  571. GLGridDraw(grid)
  572. Grid *grid;
  573. {
  574.     Geom *ltmp;
  575.  
  576.     for (ltmp = grid->unbounded; ltmp; ltmp = ltmp->next)
  577.         GeomDraw(ltmp);
  578.     for (ltmp = grid->objects; ltmp; ltmp = ltmp->next)
  579.         GeomDraw(ltmp);
  580. }
  581.  
  582. static void
  583. GLHfDraw(hf)
  584. Hf *hf;
  585. {
  586.     int x, y;
  587.     float n[3], v[3], del, del2, del4, dz1, delz, za, zb, zc;
  588.     float bot, top, left, right, len;
  589.  
  590.     del = 1. / (hf->size - 1);
  591.     del2 = del*del;
  592.     del4 = del2*del2;
  593.  
  594.     bot = 0.;
  595.     top = del;
  596.  
  597.     for (y = 0; y < hf->size -1; y++) {
  598.         za = hf->data[y+1][0];
  599.         zb = hf->data[y][0];
  600.         left = 0;
  601.         right = del;
  602.         for (x = 1; x < hf->size; x++) {
  603.             /*
  604.              * A +-+ C
  605.              *   |/
  606.              * B +
  607.              */
  608.         
  609.             zc = hf->data[y+1][x];
  610.             dz1 = za - zb;
  611.             delz = za - zc;
  612.             len = sqrt(del2*delz*delz + del2*dz1*dz1 + del4);
  613.             bgnpolygon();
  614.             n[0] = del*delz/len;
  615.             n[1] = -del*dz1/len;
  616.             n[2] = del2/len;
  617.             n3f(n);
  618.             v[0] = left; v[1] = top; v[2] = za; v3f(v);
  619.             v[1] = bot; v[2] = zb; v3f(v);
  620.             v[0] = right; v[1] = top; v[2] = zc; v3f(v);
  621.             endpolygon();
  622.  
  623.             /*
  624.              *   B +
  625.              *    /|
  626.              * A +-+ C
  627.              */
  628.             za = zb; zb = zc; zc = hf->data[y][x];
  629.             dz1 = zc - za;
  630.             delz = zc - zb;
  631.             len = sqrt(del2*dz1*dz1 + del2*delz*delz + del4);
  632.             n[0] = -del*dz1/len;
  633.             n[1] = del*delz/len;
  634.             n[2] = del2/len;
  635.             bgnpolygon();
  636.             n3f(n);
  637.             v[0] = left; v[1] = bot; v[2] = za; v3f(v);
  638.             v[0] = right; v[2] = zc; v3f(v);
  639.             v[1] = top; v[2] = zb; v3f(v);
  640.             endpolygon();
  641.             left = right;
  642.             right += del;
  643.             za = zb;
  644.             zb = zc;
  645.         }
  646.         bot = top;
  647.         top += del;
  648.     }
  649.     
  650. }
  651.  
  652. static void
  653. GLInstanceDraw(inst)
  654. Instance *inst;
  655. {
  656.     GeomDraw(inst->obj);
  657. }
  658.  
  659. static void
  660. GLListDraw(list)
  661. List *list;
  662. {
  663.     Geom *ltmp;
  664.  
  665.     for (ltmp = list->unbounded; ltmp; ltmp = ltmp->next)
  666.         GeomDraw(ltmp);
  667.     for (ltmp = list->list; ltmp; ltmp = ltmp->next)
  668.         GeomDraw(ltmp);
  669. }
  670.  
  671. static void
  672. GLPlaneDraw(plane)
  673. Plane *plane;
  674. {
  675.     /*
  676.      * Draw a really big disc.
  677.      */
  678.     GLDisc((Float)PLANE_RAD, &plane->pos, &plane->norm);
  679. }
  680.  
  681. static void
  682. GLPolygonDraw(poly)
  683. register Polygon *poly;
  684. {
  685.     register int i;
  686.  
  687.     GLNormal(&poly->norm);
  688.  
  689.     bgnpolygon();
  690.     for (i = 0; i < poly->npoints; i++)
  691.         v3d(&poly->points[i]);
  692.     endpolygon();
  693. }
  694.  
  695. static void
  696. GLSphereDraw(sph)
  697. Sphere *sph;
  698. {
  699.     pushmatrix();
  700.     translate(sph->x, sph->y, sph->z);
  701.     scale(sph->r, sph->r, sph->r);
  702.     callobj(GLSphereObject);
  703.     popmatrix();
  704. }
  705.  
  706. static void
  707. GLTorusDraw(){}
  708.  
  709. static void
  710. GLTriangleDraw(tri)
  711. register Triangle *tri;
  712. {
  713.     /*
  714.      * If Float is a double, use v3d,
  715.      * otherwise use v3f.
  716.      */
  717.     if (tri->type != PHONGTRI) {
  718.         GLNormal(&tri->nrm);    
  719.         bgnpolygon();
  720.         v3d(&tri->p[0]); v3d(&tri->p[1]); v3d(&tri->p[2]);
  721.         endpolygon();
  722.     } else {
  723.         bgnpolygon();
  724.         GLNormal(&tri->vnorm[0]);
  725.         v3d(&tri->p[0]);
  726.         GLNormal(&tri->vnorm[1]);
  727.         v3d(&tri->p[1]);
  728.         GLNormal(&tri->vnorm[2]);
  729.         v3d(&tri->p[2]);
  730.         endpolygon();
  731.     }
  732. }
  733.  
  734. float lightprops[] =    {POSITION, 0., 0., 0., 0.,
  735.              LCOLOR, 0, 0, 0,
  736.              SPOTDIRECTION, 0., 0., 0.,
  737.              SPOTLIGHT, 0., 180.,
  738.              LMNULL};
  739.  
  740. float     *lpos = &lightprops[1],
  741.     *lcolor = &lightprops[6],
  742.     *spotdir = &lightprops[10],
  743.     *spotexp = &lightprops[14],
  744.     *spotspread = &lightprops[15];
  745.  
  746. float lmodel[] =    {AMBIENT, 1., 1., 1.,
  747.              ATTENUATION, 1., 0.,
  748.              LOCALVIEWER, 0.,
  749. #ifdef sgi
  750.              ATTENUATION2, 0.,
  751.              TWOSIDE, 1.,
  752. #endif
  753.              LMNULL};
  754.  
  755. static void
  756. LightDrawInit()
  757. {
  758.     Light *light;
  759.     extern Light *Lights;
  760.  
  761.     for (light = Lights; light; light = light->next)
  762.         LightDraw(light);
  763.  
  764.     switch (curlight-1) {
  765.         case 8:
  766.             lmbind(LIGHT7, 8);
  767.         case 7:
  768.             lmbind(LIGHT6, 7);
  769.         case 6:
  770.             lmbind(LIGHT5, 6);
  771.         case 5:
  772.             lmbind(LIGHT4, 5);
  773.         case 4:
  774.             lmbind(LIGHT3, 4);
  775.         case 3:
  776.             lmbind(LIGHT2, 3);
  777.         case 2:
  778.             lmbind(LIGHT1, 2);
  779.         case 1:
  780.             lmbind(LIGHT0, 1);
  781.     }
  782.  
  783.     lmodel[1] = Options.ambient.r;
  784.     lmodel[2] = Options.ambient.g;
  785.     lmodel[3] = Options.ambient.b;
  786.  
  787.     lmdef(DEFLMODEL, 1, sizeof(lmodel) / sizeof(float), lmodel);
  788.     lmbind(LMODEL, 1);
  789. }
  790.  
  791. static void
  792. LightDraw(light)
  793. Light *light;
  794. {
  795.     if (!light || !light->methods->user)
  796.         return;
  797.     lcolor[0] = light->color.r;
  798.     lcolor[1] = light->color.g;
  799.     lcolor[2] = light->color.b;
  800.     (*light->methods->user)(light->light);
  801. }
  802.  
  803. static void
  804. GLExtendedLight(ext)
  805. Extended *ext;
  806. {
  807.     lpos[0] = ext->pos.x;
  808.     lpos[1] = ext->pos.y;
  809.     lpos[2] = ext->pos.z;
  810.     lpos[3] = 1.;
  811.     lmdef(DEFLIGHT, curlight++, sizeof(lightprops)/sizeof(float),
  812.         lightprops);
  813. }
  814.  
  815.  
  816. static void
  817. GLInfiniteLight(inf)
  818. Infinite *inf;
  819. {
  820.     lpos[0] = inf->dir.x;
  821.     lpos[1] = inf->dir.y;
  822.     lpos[2] = inf->dir.z;
  823.     lpos[3] = 0.;
  824.     lmdef(DEFLIGHT, curlight++, sizeof(lightprops)/sizeof(float),
  825.         lightprops);
  826. }
  827.  
  828. static void
  829. GLPointLight(pt)
  830. Pointlight *pt;
  831. {
  832.     lpos[0] = pt->pos.x;
  833.     lpos[1] = pt->pos.y;
  834.     lpos[2] = pt->pos.z;
  835.     lpos[3] = 1.;
  836.     lmdef(DEFLIGHT, curlight++, sizeof(lightprops) / sizeof(float),
  837.             lightprops);
  838. }
  839.  
  840. static void
  841. GLSpotLight(spot)
  842. Spotlight *spot;
  843. {
  844.     lpos[0] = spot->pos.x;
  845.     lpos[1] = spot->pos.y;
  846.     lpos[2] = spot->pos.z;
  847.     lpos[3] = 1.;
  848.     spotdir[0] = spot->dir.x;
  849.     spotdir[1] = spot->dir.y;
  850.     spotdir[2] = spot->dir.z;
  851.     *spotexp = spot->coef;
  852.     *spotspread = 180 * acos(spot->falloff) / PI;
  853.     lmdef(DEFLIGHT, curlight++, sizeof(lightprops) / sizeof(float),
  854.             lightprops);
  855.     /* fix up spot defs so other source methods needn't reset them. */
  856.     *spotspread = 180.;
  857.     *spotexp = 1.;
  858. }
  859.  
  860. static float boxfaces[6][4][3] = {
  861. {     {1., 1., 1.},
  862.     {0., 1., 1.},
  863.     {0., 0., 1.},
  864.     {1., 0., 1.}    },
  865. {    {1., 0., 1.},
  866.     {0., 0., 1.},
  867.     {0., 0., 0.},
  868.     {1., 0., 0.}    },
  869. {    {1., 0., 0.},
  870.     {0., 0., 0.},
  871.     {0., 1., 0.},
  872.     {1., 1., 0.}    },
  873. {    {0., 1., 0.},
  874.     {0., 1., 1.},
  875.     {1., 1., 1.},
  876.     {1., 1., 0.}    },
  877. {    {1., 1., 1.},
  878.     {1., 0., 1.},
  879.     {1., 0., 0.},
  880.     {1., 1., 0.}    },
  881. {    {0., 0., 1.},
  882.     {0., 1., 1.},
  883.     {0., 1., 0.},
  884.     {0., 0., 0.}}};
  885.  
  886. float boxnorms[6][3] = {
  887.     {0, 0, 1},
  888.     {0, -1, 0},
  889.     {0, 0, -1},
  890.     {0, 1, 0},
  891.     {1, 0, 0,},
  892.     {-1, 0, 0}};
  893.  
  894. /*
  895.  * Define a unit cube centered at (0.5, 0.5, 0.5)
  896.  */
  897. static Object
  898. GLBoxObjectDefine()
  899. {
  900.     int i, box;
  901.  
  902.     makeobj(box = genobj());
  903.     for (i = 0; i < 6; i++)    {
  904.         n3f(boxnorms[i]);
  905.         polf(4, boxfaces[i]);
  906.     }
  907.     closeobj();
  908.     return box;
  909. }
  910.  
  911. static void
  912. GLUnitCircle(z, up)
  913. float z;
  914. int up;
  915. {
  916.     int i;
  917.     float norm[3];
  918.  
  919.     norm[0] = norm[1] = 0.;
  920.     bgnpolygon();
  921.  
  922.     if (up) {
  923.         norm[2] = 1.;
  924.         n3f(norm);    
  925.         for (i = 0; i < CIRCLE_SAMPLES; i++) {
  926.             CirclePoints[i][2] = z;
  927.             v3f(CirclePoints[i]);
  928.         }
  929.     } else {
  930.         norm[2] = -1.;
  931.         n3f(norm);    
  932.         for (i = CIRCLE_SAMPLES -1; i; i--) {
  933.             CirclePoints[i][2] = z;
  934.             v3f(CirclePoints[i]);
  935.         }
  936.     }
  937.  
  938.     endpolygon();
  939. }
  940.  
  941. static Object
  942. GLCylObjectDefine()
  943. {
  944.     int i, j, cyl;
  945.     float norm[3];
  946.  
  947.     makeobj(cyl = genobj());
  948.     norm[2] = 0;
  949.     for (i = 0; i < CIRCLE_SAMPLES; i++) {
  950.         j = (i+1)%CIRCLE_SAMPLES;
  951.         norm[0] = CirclePoints[i][0];
  952.         norm[1] = CirclePoints[i][1];
  953. #ifdef sgi
  954.         n3f(norm);
  955.         bgnpolygon();
  956.         CirclePoints[i][2] = 0;
  957.         v3f(CirclePoints[i]);
  958.         CirclePoints[j][2] = 0;
  959.         v3f(CirclePoints[j]);
  960.         CirclePoints[j][2] = 1;
  961.         v3f(CirclePoints[j]);
  962.         CirclePoints[i][2] = 1;
  963.         v3f(CirclePoints[i]);
  964.         endpolygon();
  965. #else
  966.         n3f(norm);
  967.         pmv(CirclePoints[i][0], CirclePoints[i][1], 0.);
  968.         pdr(CirclePoints[j][0], CirclePoints[j][1], 0.);
  969.         pdr(CirclePoints[j][0], CirclePoints[j][1], 1.);
  970.         pdr(CirclePoints[i][0], CirclePoints[i][1], 1.);
  971.         pclos();
  972. #endif
  973.     }
  974.     closeobj();
  975.     return cyl;
  976. }
  977.  
  978. /*
  979.  * Fill CirclePoints[t] with X and Y values cooresponding to points
  980.  * along the unit circle.  The size of CirclePoints is equal to
  981.  * CIRCLE_SAMPLES.
  982.  */
  983. CircleDefine()
  984. {
  985.     int i;
  986.     double theta, dtheta;
  987.  
  988.     dtheta = 2.*M_PI / (double)CIRCLE_SAMPLES;
  989.     CirclePoints = (float **)malloc(CIRCLE_SAMPLES * sizeof(float *));
  990.     for (i = 0, theta = 0; i < CIRCLE_SAMPLES; i++, theta += dtheta) {
  991.         CirclePoints[i] = (float *)malloc(3 * sizeof(float));
  992.         CirclePoints[i][0] = cos(theta);
  993.         CirclePoints[i][1] = sin(theta);
  994.         /* Z is left unset. */    
  995.     }
  996. }
  997.  
  998. /*
  999.  * Given world bounds, determine near and far
  1000.  * clipping planes.  Only problem occurs when there are
  1001.  * unbbounded objects (planes)...
  1002.  */
  1003. static void
  1004. ComputeClippingPlanes(near, far, bounds)
  1005. float *near, *far;
  1006. Float bounds[2][3];
  1007. {
  1008.     Vector e, c;
  1009.     double rad, d;
  1010.  
  1011.  
  1012.     /*
  1013.      * Compute 'radius' of scene.
  1014.      */
  1015.     rad = max(max((bounds[HIGH][X] - bounds[LOW][X])*0.5,
  1016.               (bounds[HIGH][Y] - bounds[LOW][Y])*0.5),
  1017.               (bounds[HIGH][Z] - bounds[LOW][Z])*0.5);
  1018.  
  1019.     c.x = (bounds[LOW][X] + bounds[HIGH][X])*0.5;
  1020.     c.y = (bounds[LOW][Y] + bounds[HIGH][Y])*0.5;
  1021.     c.z = (bounds[LOW][Z] + bounds[HIGH][Z])*0.5;
  1022.  
  1023.     /*
  1024.      * Compute position of eye relative to the center of the sphere.
  1025.      */
  1026.     VecSub(Camera.pos, c, &e);
  1027.     d = VecNormalize(&e);
  1028.     if (d <= rad)
  1029.         /*
  1030.          * Eye is inside sphere.
  1031.          */
  1032.         *near = DEFAULT_NEAR;
  1033.     else
  1034.         *near = (d - rad)*0.2;
  1035.     *far = (d + rad)*2.;
  1036. }
  1037.